#include <stdio.h>
#include <string.h>
#include <sndfile.h>
#include <speex/speex_echo.h>
#include <speex/speex_preprocess.h>
#include <speex/speex_resampler.h>
#include "wavtool.h"

#define AGC_DEFAULT_TARGET				8000
#define AGC_DEFAULT_MAX_GAIN			12
#define AGC_DEFAULT_DECREMENT			-60

WavTool::WavTool(){}

SpeexPreprocessState* preproc_create(int samplerate)
{
        SpeexPreprocessState* preproc = speex_preprocess_state_init(128, samplerate);

        // Enable AGC
        int val = 1;
        speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_AGC, &val);

        // Disable other
        val = 0;
        speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_DENOISE, &val);
        speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_DEREVERB, &val);
        speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_VAD, &val);

        val = AGC_DEFAULT_TARGET; // 8000 ~24% -- Default: 8000 ~24%
        speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_AGC_TARGET, &val);

        val = AGC_DEFAULT_MAX_GAIN; // +12dB -- Default 30dB
        speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &val);

        val = AGC_DEFAULT_DECREMENT; // -60dB per second -- Default -40dB
        speex_preprocess_ctl(preproc, SPEEX_PREPROCESS_SET_AGC_DECREMENT, &val);

        return preproc;

}

void WavTool::addNote(const char* infilename, float start,float length)
{


        SF_INFO info;
        memset(&info,0,sizeof(info));
        SNDFILE* infile = sf_open(infilename,SFM_READ,&info);

        SpeexPreprocessState* preproc = preproc_create(info.samplerate);
        SpeexResamplerState *resampler = nullptr;

        wavdata* ret=new wavdata;
        ret->start=start;
        ret->length=length;

        int err=0;
        if(info.samplerate != _outputRate)
            resampler = speex_resampler_init(1, info.samplerate, _outputRate, 10, &err);

        //info.samplerate = output_rate;
        //SNDFILE* outfile = sf_open(outfilename,SFM_WRITE,&info);

        short data[128];
        short data2[1024];

        //store wav data

        while(1)
        {
            int count = sf_read_short(infile,data,128);
            speex_preprocess_run(preproc, data);
            for(int i=0;i<128;i++) data[i]*=0.9;

            int data2_length = 1024;
            if(resampler) {

                speex_resampler_process_int(resampler,0,data,(spx_uint32_t*)&count,data2,(spx_uint32_t*)&data2_length);
                for(int i=0;i<data2_length;i++) ret->data.push_back(data2[i]*1.0/32768);
            }

            if(count<128) break;
        }



        speex_preprocess_state_destroy(preproc);
        sf_close(infile);
            if(resampler) speex_resampler_destroy(resampler);

        _notes.push_back(ret);
}

void WavTool::mix()
{
    float songLength = _notes[_notes.size()-1]->start + _notes[_notes.size()-1]->length;
    _outdataLength = _outputRate*songLength;
    _outdata = new float[_outdataLength];

    for(int i=0;i<(int)_notes.size();i++)
    {
        float start = _notes[i]->start;
        float end = start+_notes[i]->length;
        int startix = _outputRate*start;
        int endix = _outputRate*end;
        int count = endix-startix;

        //fprintf(stderr,"%i %i\n",startix,endix);
        for(int j=0;j<count;j++)
        {
            int index = j+startix;
            if(index>0 && index<_outdataLength && j<_notes[i]->data.size()) _outdata[index]+=_notes[i]->data[j];
        }
    }

    SF_INFO info;
    memset(&info,0,sizeof(info));
    info.channels=1;
    info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
    info.samplerate = _outputRate;

    SNDFILE* sf= sf_open("/tmp/wavtool.wav",SFM_WRITE,&info);
    sf_write_float(sf,_outdata,_outdataLength);
    sf_close(sf);



    //fprintf(stderr,"songLength %f\n",songLength);
}

void WavTool::clear()
{
   _notes.clear();
   //TODO: delete memory
}
